/*
 * Copyright (c) 2022 Hong Jiahua
 * https://gitee.com/arrco/jh_stack
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
#ifndef __JH_STACK_H__
#define __JH_STACK_H__

#include <string.h>
#include <stdlib.h>
/************************************************************************/
/*                                                                      */
/************************************************************************/
/*是否支持动态申请空间*/
// #define JH_STACK_DYNAMIC_SPACE

#ifdef JH_STACK_DYNAMIC_SPACE

#define JH_STACK_MALLOC malloc
#define JH_STACK_FREE   free

#endif

/************************************************************************/
/*                                                                      */
/************************************************************************/

/**
  * @brief  栈数据结构
  */
typedef struct {
    void* base;
    size_t num;
    size_t size;
    size_t data_len;
} jh_stack_t;

/**
  * @brief  栈数据迭代
  */
#define JH_STACK_ITER(stack, item)  \
    for(size_t jh_i = (stack)->data_len > 0 ? memcpy(item, (stack)->base + ((stack)->data_len - 1) * (stack)->size, (stack)->size) , (stack)->data_len : 0;  \
        jh_i > 0; jh_i--, jh_i = jh_i > 0 ? (memcpy(item, (stack)->base + (jh_i - 1) * (stack)->size, (stack)->size) , jh_i) : 0)

/**
  * @brief  栈数据反向迭代
  */
#define JH_STACK_ITER_REVERSE(stack, item)  \
    for(size_t jh_i = (stack)->data_len > 0 ? memcpy(item, (stack)->base, (stack)->size) , 0 : 0;  \
        jh_i < (stack)->data_len; jh_i++, jh_i = jh_i < (stack)->data_len ? (memcpy(item, (stack)->base + jh_i * (stack)->size, (stack)->size) , jh_i) : (stack)->data_len)

/*判断栈是否为空*/
int jh_stack_is_empty(jh_stack_t* stack);
/*判断栈是否已满*/
int jh_stack_is_full(jh_stack_t* stack);
/*获取栈的数据数量*/
size_t jh_stack_count(jh_stack_t* stack);
/*入栈*/
int jh_stack_push(jh_stack_t* stack, void* item);
/*出栈*/
int jh_stack_pop(jh_stack_t* stack, void* item);
/*查看栈顶的数据*/
int jh_stack_peek(jh_stack_t* stack, void* item);
/*查看栈底的数据*/
int jh_stack_peek_bottom(jh_stack_t* stack, void* item);
/*清空栈*/
int jh_stack_clear(jh_stack_t* stack);
/*栈数据排序*/
int jh_stack_sort(jh_stack_t* stack, int (*compare)(const void*, const void*));
/*栈初始化*/
int jh_stack_init(jh_stack_t* stack, void* base, size_t num, size_t size);

#ifdef JH_STACK_DYNAMIC_SPACE
/*栈空间申请*/
int jh_stack_space_malloc(jh_stack_t* stack, size_t num, size_t size);
/*栈空间释放*/
int jh_stack_space_free(jh_stack_t* stack);
#endif

#endif